

#ifndef _UTLI_HPP_
#define _UTLI_HPP_
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include "include/cppjieba/Jieba.hpp"
#include <unordered_map>
#include "log.hpp"
typedef struct file_info
{
    std::string title;
    std::string content;
    std::string url; // 官网访问的url
} file_info_t;

bool Parsertitle(const std::string &file_result, file_info_t *info)
{
    std::size_t begin_pos = file_result.find("<title>");
    if (begin_pos == std::string::npos)
    {
        return false;
    }
    std::size_t end_pos = file_result.find("</title>");
    if (end_pos == std::string::npos)
    {
        return false;
    }
    begin_pos += std::string("<title>").size();
    if (begin_pos > end_pos)
    {
        return false;
    }
    info->title = file_result.substr(begin_pos, end_pos - begin_pos);
    return true;
}

// 使用状态机提取文件内容
bool ParserContent(const std::string &file_result, file_info_t *info)
{
    // 使用状态机
    enum status
    {
        LABLES,
        CONTENT
    };
    std::string content;
    enum status s = LABLES;
    for (auto ch : file_result)
    {
        switch (s)
        {
        case LABLES:
            if (ch == '>')
            {
                s = CONTENT;
            }
            break;
        case CONTENT:
            if (ch == '<')
            {
                s = LABLES;
            }
            else
            {
                if (ch == '\n')
                {
                    ch = ' ';
                }
                content.push_back(ch);
            }
            break;
        default:
            break;
        }
    }
    info->content = content;
    return true;
}

// input下的每一个html网页都与boost官网一一对应
bool ParserUrl(const std::string &file_path, file_info_t *info)
{
    const std::string url_head = "https://www.boost.org/doc/libs/1_80_0/doc/html";
    std::string src_path = "data/input";
    const std::string url_tail = file_path.substr(src_path.size());
    info->url = url_head + url_tail;
    // std::cout<<"debug: "<<info->url<<std::endl;
    return true;
}

namespace ns_util
{
    class Fileutil
    {
    public:
        static bool ReadFile(const std::string &file_path, std::string *out)
        {
            std::ifstream in(file_path, std::ios::in);
            if (!in.is_open())
            {
                std::cerr << "file open err" << std::endl;
                return false;
            }
            std::string line;
            while (std::getline(in, line))
            { // 这里使用了强制类型转化，将ifstream类转化为了bool
                *out += line;
            }
            in.close();
            return true;
        }
    };
    class Stringutli
    {

    public:
        static void Split(const std::string &target, std::vector<std::string> *resstring, const std::string &sep)
        {
            // 使用boost库的库函数分割字符串
            boost::split(*resstring, target, boost::is_any_of(sep), boost::token_compress_on);
        }
    };

    const char *const DICT_PATH = "./dict/jieba.dict.utf8";
    const char *const HMM_PATH = "./dict/hmm_model.utf8";
    const char *const USER_DICT_PATH = "./dict/user.dict.utf8";
    const char *const IDF_PATH = "./dict/idf.utf8";
    const char *const STOP_WORD_PATH = "./dict/stop_words.utf8";

    class JiebaUtil
    {
    public:
        static void CutString(std::string word, std::vector<std::string> *vec)
        {
            Getinstance()->CutStringHelper(word,vec);
        }

        static JiebaUtil *Getinstance()
        {
            if (instance == nullptr)
            {
                mtx.lock();
                if (instance == nullptr)
                {
                    instance = new JiebaUtil();
                }
                mtx.unlock();
            }
            return instance;
        }

    private:
        std::unordered_map<std::string, bool> stopwords;
        // 去掉暂停分词
        void CutStringHelper(const std::string &src, std::vector<std::string> *out)
        {
            jieba.CutForSearch(src, *out);
            readstopwords();
            for (auto it = out->begin(); it != out->end();)
            {
                auto iter = stopwords.find(*it);
                if (iter == stopwords.end())
                {
                    it++;
                }
                else
                {
                    it = out->erase(it);
                }
            }
        }

        // 读取暂停词
        void readstopwords()
        {
            std::ifstream in(STOP_WORD_PATH);
            if (!in.is_open())
            {
                LOG(FATAL, "STOP_WORD_PATH file open err!");
                return;
            }
            std::string line;
            while (std::getline(in, line))
            {
                stopwords.insert({line, true});
            }
            in.close();
        }

        cppjieba::Jieba jieba;
        JiebaUtil()
            : jieba(DICT_PATH, HMM_PATH, USER_DICT_PATH, IDF_PATH, STOP_WORD_PATH)
        {
        }
        JiebaUtil(const JiebaUtil &) = delete;
        static JiebaUtil *instance;
        // 锁
        static std::mutex mtx;
    };
    JiebaUtil *JiebaUtil::instance = nullptr;
    std::mutex JiebaUtil::mtx;
};

#endif